<!DOCTYPE html>

<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>BreadKnife</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="Field and method binding for Android views.">
    <link href="https://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic,bold" rel="stylesheet" title="roboto">
    <link href="static/bootstrap.min.css" rel="stylesheet">
    <link href="static/bootstrap-responsive.min.css" rel="stylesheet">
    <link href="static/prettify.css" rel="stylesheet">
    <link href="static/app.css" rel="stylesheet">
  </head>
  <body>
    <div class="container">
      <div class="row">
        <div class="span4 side">
          <img src="static/logo.png">
          <br/><br/>
          <p><a href="index.html" style="color:dkgray;font-size:15px;font-weight:bold;">EN</a> | <a href="index_CN.html" style="color:dkgray;font-size:15px;font-weight:bold;">中文简体</a></p>
          <h1 style="color:blue;font-weight:bold;">BreadKnife</h1>
          <h2 style="color:dkgray;font-weight:bold;">数据绑定、布局绑定、控件绑定、事件绑定、数据异常预处理、开发更加简单。</h2>
          <p><a href="javadoc/index.html" target="_blank" style="color:dkgray;font-size:15px;font-weight:bold;">Java文档</a> &middot; <a href="http://stackoverflow.com/questions/ask?tags=breadknife" target="_blank" style="color:dkgray;font-size:15px;font-weight:bold;">StackOverflow</a></p>
        </div>
        <div class="offset4 span8 main">
          <div class="main-inner">
              <h3 id="feature">特点</h3>
              <p>● 支持MVVM(Model-View-ViewModel)</p>
              <p>● 支持任意数据类型绑定(包含自定义控件)</p>
              <p>● 支持任意类绑定(Activity、Fragment、Dialog、View 如果有需要普通类也可以)</p>
              <p>● 规避空指针引发的异常(防止项目开发中，数据异常引起的空指针)</p>
              <p>● 支持View绑定(我不建议你这样做，因为根本没有必要)</p>
              <p>● 支持点击事件双向绑定(Activity中绑、layout中也可以)</p>
              <p>● 支持长按点击事件绑定</p>
              <p>● 支持library、application</p>
              <p>● 支持布局绑定</p>
              <p>● 支持简单比较运算</p>
              <h3 id="summary">概述</h3>
              <p>BreadKnife能够避免在项目开发中一些重复繁琐的工作，规避因数据异常引发的空指针异常，提高开发效率。它量身为 <a href="https://baike.baidu.com/item/MVVM">MVVM</a> 框架打造，实现UI逻辑与业务分离，解耦，提高可重用性。
                  它提供了3种注解方式，9种xml属性完成数据绑定，事件绑定等操作。</p>
              <p><span>9种xml属性：</span></p>
                  <table width="400" cellspacing="0">
                      <thead>
                      <tr>
                          <th style='text-align:center;' ><span>属性</span></th>
                          <th style='text-align:center;' ><span>功能</span></th>
                          <th style='text-align:center;' ><span>控件</span></th>
                      </tr>
                      </thead>
                      <tbody>
                      <tr><td style='text-align:center;' ><span>imports</span></td>
                          <td style='text-align:center;' ><span>引入需要绑定的类</span></td>
                          <td style='text-align:center;' ><span>root view</span></td>
                      </tr>
                      <tr>
                          <td style='text-align:center;' ><span>viewModel</span></td>
                          <td style='text-align:center;' ><span>引入Viewmodel</span></td>
                          <td style='text-align:center;' ><span>root view</span></td>
                      </tr>
                      <tr>
                          <td style='text-align:center;' ><span>bind</span></td>
                          <td style='text-align:center;' ><span>绑定数据</span></td>
                          <td style='text-align:center;' ><span>view</span></td>
                      </tr>
                      <tr>
                          <td style='text-align:center;' ><span>click</span></td>
                          <td style='text-align:center;' ><span>点击监听</span></td>
                          <td style='text-align:center;' ><span>view</span></td>
                      </tr>
                      <tr>
                          <td style='text-align:center;' ><span>longClick</span></td>
                          <td style='text-align:center;' ><span>长按监听</span></td>
                          <td style='text-align:center;' ><span>view</span></td>
                      </tr>
                      <tr>
                          <td style='text-align:center;' ><span>textChanged</span></td>
                          <td style='text-align:center;' ><span>文本变化监听</span></td>
                          <td style='text-align:center;' ><span>TextView</span></td>
                      </tr>
                      <tr>
                          <td style='text-align:center;' ><span>checkChanged</span></td>
                          <td style='text-align:center;' ><span>选择变化监听</span></td>
                          <td style='text-align:center;' ><span>CheckBox</span></td>
                      </tr>
                      <tr>
                          <td style='text-align:center;' ><span>tabSelected</span></td>
                          <td style='text-align:center;' ><span>选择变化监听</span></td>
                          <td style='text-align:center;' ><span>TabLayout</span></td>
                      </tr>
                      <tr>
                          <td style='text-align:center;' ><span>tabUnselected</span></td>
                          <td style='text-align:center;' ><span>选择变化监听</span></td>
                          <td style='text-align:center;' ><span>TabLayout</span></td>
                      </tr>
                      <tr>
                          <td style='text-align:center;' ><span>pageSelected</span></td>
                          <td style='text-align:center;' ><span>选择变化监听</span></td>
                          <td style='text-align:center;' ><span>ViewPager</span></td>
                      </tr>
                      <tr>
                          <td style='text-align:center;' ><span>progressChanged</span></td>
                          <td style='text-align:center;' ><span>进度变化监听</span></td>
                          <td style='text-align:center;' ><span>SeekBar</span></td>
                      </tr>
                      <tr>
                          <td style='text-align:center;' ><span>radioChanged</span></td>
                          <td style='text-align:center;' ><span>选择变化监听</span></td>
                          <td style='text-align:center;' ><span>RadioButton</span></td>
                      </tr>
                      </tbody>
                  </table>

              <br/>

              <p><span>3种注解：</span></p>
                  <table width="400" cellspacing="0">
                      <thead>
                      <tr>
                          <th style='text-align:center;' ><span>注解</span></th>
                          <th style='text-align:center;' ><span>功能</span></th>
                      </tr>
                      </thead>
                      <tbody>
                      <tr>
                          <td style='text-align:center;' ><span>BindLayout</span></td>
                          <td style='text-align:center;' ><span>绑定布局，并解析布局文件</span></td>
                      </tr>
                      <tr>
                          <td style='text-align:center;' ><span>BindView</span></td>
                          <td style='text-align:center;' ><span>绑定控件</span></td>
                      </tr>
                      <tr>
                          <td style='text-align:center;' ><span>BindClick</span></td>
                          <td style='text-align:center;' ><span>绑定事件</span></td>
                      </tr>
                      <tr>
                          <td style='text-align:center;' ><span>Immersive</span></td>
                          <td style='text-align:center;' ><span>沉浸式</span></td>
                      </tr>
                      </tbody>
                  </table>

            <h3 id="compare">比较</h3>
              <table width="600" cellspacing="0">
                <thead>
                  <tr>
                      <th style='text-align:center;' >&nbsp;</th>
                      <th style='text-align:center;' ><span>注解控件</span></th>
                      <th style='text-align:center;' ><span>注解方法</span></th>
                      <th style='text-align:center;' ><span>注解布局</span></th>
                      <th style='text-align:center;' ><span>数据绑定</span></th>
                      <th style='text-align:center;' ><span>任意绑定</span></th>
                      <th style='text-align:center;' ><span>事件传递</span></th><th style='text-align:center;' ><span>学习成本</span></th>
                  </tr>
                  </thead>
                  <tbody>
                    <tr>
                        <td style='text-align:center;' ><span>BreadKnife</span></td>
                        <td style='text-align:center;' ><span>支持</span></td>
                        <td style='text-align:center;' ><span>支持</span></td>
                        <td style='text-align:center;' ><span>支持</span></td>
                        <td style='text-align:center;' ><span>支持</span></td>
                        <td style='text-align:center;' ><span>支持</span></td>
                        <td style='text-align:center;' ><span>支持</span></td>
                        <td style='text-align:center;' ><span>低</span></td>
                    </tr>
                    <tr>
                        <td style='text-align:center;' ><span>Databinding</span></td>
                        <td style='text-align:center;' ><span>不支持</span></td>
                        <td style='text-align:center;' ><span>不支持</span></td>
                        <td style='text-align:center;' ><span>不支持</span></td>
                        <td style='text-align:center;' ><span>支持</span></td>
                        <td style='text-align:center;' ><span>不支持</span></td>
                        <td style='text-align:center;' ><span>支持</span></td>
                        <td style='text-align:center;' ><span>高</span></td>
                    </tr>
                    <tr>
                        <td style='text-align:center;' ><span>ButterKnife</span></td>
                        <td style='text-align:center;' ><span>支持</span></td><td style='text-align:center;' ><span>支持</span></td>
                        <td style='text-align:center;' ><span>不支持</span></td><td style='text-align:center;' ><span>不支持</span></td>
                        <td style='text-align:center;' ><span>不支持</span></td>
                        <td style='text-align:center;' ><span>不支持</span></td>
                        <td style='text-align:center;' ><span>低</span></td>
                    </tr>
                    <tr>
                        <td style='text-align:center;' ><span>XUtil</span></td>
                        <td style='text-align:center;' ><span>支持</span></td>
                        <td style='text-align:center;' ><span>支持</span></td>
                        <td style='text-align:center;' ><span>不支持</span></td>
                        <td style='text-align:center;' ><span>不支持</span></td>
                        <td style='text-align:center;' ><span>不支持</span></td>
                        <td style='text-align:center;' ><span>不支持</span></td>
                        <td style='text-align:center;' ><span>中</span></td>
                    </tr>
                  </tbody>
              </table>

            <h3 id="description">使用说明</h3>
            <p>1. 在使用<code>BreadKnife</code>提供的功能之前，必须调用<code>BreadKnife.bind</code>方法，该方法会返回<code>UnBinder</code>的一个实现类。</p>
            <p>2. 在绑定和引入类中，如果你需要绑定多个数据，或者引入多个类，请使用<code>"|"</code>符号隔开。</p>
            <p>3. <code>"$"</code>符号必须是成对使用的，使用<code>"$"</code>引起来的变量表示是需要变换的。</p>

              <h3 id="introduction_annotation">>> 注解使用说明</h3>
              <h4 id="intro">功能入口</h4>
              <p><code>BeadKnife.bind</code>方法为功能入口，该方法会返回<code>UnBinder</code>接口的一个实现类对象，该方法必须在使用BeadKnife提供的功能之前调用。</p>
              <p>建议该方法基类中使用。避免子类重复操作。</p>
              <h4 id="intro_activity">Activity中使用</h4>
<pre class="prettyprint">
public abstract class BaseActivity<T extends UnBinder> extends AppCompatActivity {
    T unbinder;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        unbinder = (T) BreadKnife.bind(this);
     }
}</pre>
              <h4 id="intro_fragment">Fragment中使用</h4>
<pre class="prettyprint">
public abstract class BaseFragment<T extends UnBinder> extends Fragment {

    T unbinder;

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(attachLayoutRes(), container, false);
        unbinder = (T) BreadKnife.bind(this, view);
        return view;
    }

    protected abstract int attachLayoutRes();
}</pre>
              <h4 id="intro_dialog">Dialog中使用</h4>
<pre class="prettyprint">
public abstract class BaseDialog<T extends UnBinder> extends Dialog {
    T unbinder;
    public BaseDialog(@NonNull Context context) {
        super(context);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        View view=View.inflate(getContext(),attachLayouRes(),null);
        setContentView(view);
        unbinder= (T) BreadKnife.bind(this,view);
    }

    protected abstract int  attachLayouRes();
}</pre>

              <h4 id="intro_annotations">注解类型</h4>
              <p><code>BindLayout</code>、<code>BindView</code>、<code>BindClick</code>均可以根据需求任意类中使用，make project [🔨]，会自动生成该 “<code>类名+UnBinder</code>” 的类，和唯一个<code>ViewInjector</code>类(和数据绑定相关)，<code>UnBinder</code>子类提供了所有你需要的功能。<code>ViewInjector</code>这里不提，后续数据绑定会讲到。</p>
              <h4 id="intro_bindlayout">BindLayout</h4>
              <p>功能为绑定布局（不用setContentView），同时解析布局文件。<br/><b>注意：该方法绑定布局功能针对Activity类。</b></p>
<pre class="prettyprint">
@BindLayout(value = R.layout.activity_demo, rootPackage = "com.lzw.breadknife.sample")
public class DemoActivity extends BaseActivity<DemoActivityUnBinder> {

    @Override
    protected int attachTitleRes() {
        return R.string.title_demo;
    }

    public void onRecyclerViewClick() {
        startActivity(RecyclerViewActivity.class);
    }

    public void onNormalClick() {
        startActivity(NormalActivity.class);
    }

    public void onMultipleClick(String trim) {
        Toast.makeText(DemoActivity.this, trim, Toast.LENGTH_SHORT).show();
        startActivity(MultipleActivity.class);
    }
}</pre>
              <p>自动生成的类如下所示：</p>
<pre class="prettyprint">
public class DemoActivityUnBinder implements UnBinder<DemoActivity> {
    public ImageView toolBar_back;
    public TextView toolBar_title;
    public Button btn_bind_normal;
    public Button btn_bind_data_error;
    public Button btn_bind_recycler;

    @Override
    public void bind(final DemoActivity host, Object source) {
        if (!Utils.contentViewExist(host)) {
            host.setContentView(R.layout.activity_demo);
        }
        toolBar_back = (ImageView) host.findViewById(R.id.toolBar_back);
        toolBar_title = (TextView) host.findViewById(R.id.toolBar_title);
        btn_bind_normal = (Button) host.findViewById(R.id.btn_bind_normal);
        btn_bind_data_error = (Button) host.findViewById(R.id.btn_bind_data_error);
        btn_bind_recycler = (Button) host.findViewById(R.id.btn_bind_recycler);
        btn_bind_normal.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                host.onNormalClick();
            }
        });
        btn_bind_data_error.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                host.onMultipleClick(btn_bind_data_error.getText().toString().trim());
            }
        });
        btn_bind_recycler.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                host.onRecyclerViewClick();
            }
        });
    }

    @Override
    public void clear() {
    }
    @Override
    public void clearAll() {
        this.toolBar_back = null;
        this.toolBar_title = null;
        this.btn_bind_normal = null;
        this.btn_bind_data_error = null;
        this.btn_bind_recycler = null;
    }
}</pre>
              <h4 id="intro_bindview">BindView、BindClick</h4>
              <p>功能主要分别为绑定控件，绑定单击事件，基本上没有用，除了一些特殊应用，比如在基类中。</p>
<pre class="prettyprint">
public abstract class BaseActivity<T extends UnBinder> extends AppCompatActivity {
    T unbinder;
    @BindView(R.id.toolBar_title)
    TextView toolBar_title;

//    @BindView({R.id.text1,R.id.text2,R.id.text3})
//    TextView[] textViews;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        unbinder = (T) BreadKnife.bind(this);
        toolBar_title.setText(attachTitleRes());
    }


    @BindClick(R.id.toolBar_back)
    public void OnBackClick(View v) {
        finish();
    }
    protected abstract int attachTitleRes();

    protected void startActivity(Class<? extends AppCompatActivity> clazz) {
        Intent intent = new Intent(this, clazz);
        startActivity(intent);
    }
}</pre>
              <p>自动生成的类如下所示：</p>
<pre class="prettyprint">
public class BaseActivityUnBinder implements UnBinder<BaseActivity> {

    @Override
    public void bind(final BaseActivity host, Object source) {
        host.toolBar_title = (TextView) host.findViewById(R.id.toolBar_title);
        host.findViewById(R.id.toolBar_back).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                host.OnBackClick(v);
            }
        });
    }

    @Override
    public void clear() {
    }

    @Override
    public void clearAll() {
    }
}</pre>

              <h3 id="introduction_xml">>> XML属性标签使用说明</h3>

              <p>BeadKnife使用的属性标签Android控件并没有提供，需要在根布局中添加如下属性(<code>tools:ignore="MissingPrefix"</code>)。</p>
              <pre class="prettyprint">
&lt; xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:ignore="MissingPrefix">
&lt;/LinearLayout&gt;
</pre>

              <h4>使用import绑定数据类</h4>

              <p>根布局中引入需要绑定的数据源，并设置别名，数据源与别名用英文“,”隔开。如果需要绑定多个数据源请采用“|”符号隔开。同时会在UnBinder的实现类中生成
                  [set + 别名] 的方法，用于绑定数据。</p>

              <pre class="prettyprint">
&lt; xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    app:imports="com.lzw.breadknife.sample.bean.Multiple,mul|com.lzw.breadknife.sample.bean.MulObj,obj"
    tools:ignore="MissingPrefix"&gt;
&lt;/LinearLayout&gt;
</pre>

              <p>自动生成</p>

              <pre class="prettyprint">
public class MultipleActivityUnBinder implements UnBinder<MultipleActivity> {

    ...
    public void setMul(Multiple mul) {
        if (mul == null) return;
    }

    public void setObj(MulObj obj) {
        if (obj == null) return;
    }
    ...
}
</pre>

              <h4>使用import绑定数据类</h4>

              <p>需要绑定数据的控件必须添加android:id标签，数据源需要用成对的“$”符号包裹起来，如果有多个数据，需要用“|”隔开。</p>

              <pre class="prettyprint">
        &lt;!--&lt;TextView--&gt;
            &lt;!--android:id="@+id/tv_sex"--&gt;
            &lt;!--style="@style/text_childer"--&gt;
            &lt;!--app:bind="$mul.gender$|$obj.star$" /&gt;--&gt;
        &lt;TextView
            android:id="@+id/tv_sex"
            style="@style/text_childer"
            app:bind="$mul.gender$|$mul.genderColor$" /&gt;
        &lt;TextView
            android:id="@+id/tv_star"
            style="@style/text_childer"
            app:bind="$obj.star$" /&gt;
</pre>

              <p>自动生成</p>

              <pre class="prettyprint">
public class MultipleActivityUnBinder implements UnBinder<MultipleActivity> {

    ...
    public void setMul(Multiple mul) {
        if (mul == null) return;
        BreadKnifeInjector.injector(tv_sex,mul.getGender());
        BreadKnifeInjector.injector(tv_sex,mul.getGenderColor());
    }

    public void setObj(MulObj obj) {
        if (obj == null) return;
        BreadKnifeInjector.injector(tv_star,obj.getStar());
    }
    ...
}
</pre>

              <p>数据绑定会先通过BreadKnifeInjector.injector进入</p>

              <pre class="prettyprint">
public class BreadKnifeInjector {
    public static void injector(View view, Object value) {
        if (value == null | view == null) {
        } else if (ViewInjector.injector(view, value)) {
        } else if (view instanceof ImageView) {
            injectImageView((ImageView) view, value);
        } else if (view instanceof Button) {
            injectButton((Button) view, value);
        } else if (view instanceof EditText) {
            injectEditText((EditText) view, value);
        } else if (view instanceof TextView) {
            injectTextView((TextView) view, value);
        } else {
            Log.e("BreadKnife", "No match method and can not inject " + view.getClass().getSimpleName());
        }
    }
    ...
}
</pre>

              <p>验证数据是否正常，然后进入之前提到的ViewInjector，该类在[包名.elementsBean.ViewInjector]，由你决定是否绑定数据，如果绑定[ture]则拦截，否则使用内置的BreadKnifeInjector。<br/>
                  在这里可以实现这自定义控件绑定数据，一些特殊数据源，比如：加载图片、字体颜色、背景色、是否显示等。</p>

              <pre class="prettyprint">
public class ViewInjector {
    public static boolean injector(View view, Object value) {
        if (view instanceof View && value instanceof ViewState) {
            view.setVisibility(value == ViewState.SHOW ? View.VISIBLE : View.GONE);
            return true;
        } else if (view instanceof TextView && value instanceof TextColor) {
            ((TextView) view).setTextColor(view.getResources().getColor(((TextColor) value).getColor()));
            return true;
        } else {
            return false;
        }
    }
}
</pre>

              <h4>click longClick</h4>

              <p>单击，长按事件的控件必须添加android:id标签。如果需要传出需要变换数据的数据源，请使用成对“$”符号，如果需要相应多个点击事件，请用“|”隔开。</p>

              <pre class="prettyprint">
    &lt;Button
        android:id="@+id/btn_bind_data_error"
        app:click="onMultipleClick($btn_bind_data_error$)" /&gt;

    &lt;Button
        android:id="@+id/btn_bind_recycler"
        app:click="onRecyclerViewClick" /&gt;
</pre>

              <p>自动生成</p>

              <pre class="prettyprint">
public class DemoActivityUnBinder implements UnBinder<DemoActivity> {
    public Button btn_bind_data_error;
    public Button btn_bind_recycler;
    ...
    @Override
    public void bind(final DemoActivity host, Object source) {
        ...
        btn_bind_data_error = (Button) host.findViewById(R.id.btn_bind_data_error);
        btn_bind_recycler = (Button) host.findViewById(R.id.btn_bind_recycler);
        btn_bind_data_error.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                host.onMultipleClick(btn_bind_data_error.getText().toString().trim());
            }
        });
        btn_bind_recycler.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                host.onRecyclerViewClick();
            }
        });
    }
    ...
}
</pre>

              <h4>viewModel</h4>

              <p>引入需要绑定ViewModel接口</p>

              <pre class="prettyprint">
&lt; xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    app:viewModel="com.lzw.breadknife.sample.mvvm.viewmodel.ILoginViewModel"
    tools:ignore="MissingPrefix"&gt;
</pre>

              <p>自动生成</p>

              <pre class="prettyprint">
public class LoginActivityUnBinder implements UnBinder<LoginActivity> {

    public ILoginViewModel viewModel;
    ...
    @Override
    public void bindViewModel(Object viewModel) {
        this.viewModel = (ILoginViewModel) viewModel;
    }
}
</pre>

              <h4>transfer longTransfer</h4>

              <p>向viewModel发送单击消息和长按消息，应用方式和click longClick一样。</p>

              <pre class="prettyprint">
    &lt;EditText
        android:id="@+id/et_account"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginHorizontal="40dp"
        android:layout_marginVertical="10dp"
        android:hint="账号" /&gt;

    &lt;EditText
        android:id="@+id/et_pswd"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginHorizontal="40dp"
        android:layout_marginVertical="10dp"
        android:hint="密码" /&gt;

    &lt;Button
        android:id="@+id/btn_login"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginHorizontal="40dp"
        android:layout_marginVertical="10dp"
        android:text="登陆"
        app:transfer="onLoginClick($et_account$,$et_pswd$)" /&gt;
</pre>

              <p>自动生成</p>

              <pre class="prettyprint">
public class LoginActivityUnBinder implements UnBinder<LoginActivity> {
    public EditText et_account;
    public EditText et_pswd;
    public Button btn_login;
    public LoginResult result;
    public ILoginViewModel viewModel;
    ...
    @Override
    public void bind(final LoginActivity host, Object source) {
        if (!Utils.contentViewExist(host)) {
            host.setContentView(R.layout.activity_login);
        }
        et_account = (EditText) host.findViewById(R.id.et_account);
        et_pswd = (EditText) host.findViewById(R.id.et_pswd);
        btn_login = (Button) host.findViewById(R.id.btn_login);
        btn_login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                viewModel.onLoginClick(et_account.getText().toString().trim() , et_pswd.getText().toString().trim());
            }
        });

    }

    @Override
    public void bindViewModel(Object viewModel) {
        this.viewModel = (ILoginViewModel) viewModel;
    }
    ...
}
</pre>

            <h3 id="download">下载</h3>
            <p>由于没有上传到Maven仓库，这里选择jar方式添加依赖：</p>
            <h4>1.拷贝<code>repo</code>到你项目的根路径。</h4>
              <p></p>
            <h4>2.在您项目根路径的 <code>build.gralde</code> 添加以下配置：</h4>
<pre class="prettyprint">
buildscript {

    repositories {
        // 使用本地生成的plugin仓库
        maven {
            allowInsecureProtocol(true)
            url uri("./repo")
        }
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:7.2.2'
        // 插件使用了kotlin，所以需要添加kotlin相关配置：
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.20"
        // 这个必须添加：使用本地生成的plugin仓库
        classpath "com.lzw.breadknife:BreadKnife-Plugin:3.0.0"
    }
}

allprojects {
    repositories {
        // 使用本地生成的plugin仓库
        maven {
            allowInsecureProtocol(true)
            url uri("./repo")
        }
    }
    // 添加额外配置，比如：中文支持
    tasks.withType(Javadoc) {
        options.addStringOption('Xdoclint:none', '-quiet')
        options.addStringOption('encoding', 'UTF-8')
    }
}
</pre>
              <p></p>
              <h4>3.拷贝<code>aars</code>目录的<code>breadknife-release-3.0.0.aar</code>，<code>breadknife-annotation-release-3.0.0.jar</code>，<code>breadknife-compiler-release-3.0.0.jar</code>以及<code>Immersive-release-3.0.0.aar</code>到您<code>module</code>的<code>libs</code>文件夹。</h4>
              <p></p>
              <h4>4.在您项目的module的 <code>build.gralde</code> 添加以下配置：</h4>
<pre class="prettyprint">
apply plugin: 'com.lzw.breadknife'

dependencies {

    implementation files('libs\\breadknife-release-3.0.0.aar')
    implementation files('libs\\breadknife-annotation-release-3.0.0.jar')
    annotationProcessor files('libs\\breadknife-compiler-release-3.0.0.jar')

    // 可选，如有沉浸式状态栏需求，可以添加该库
    implementation files('libs\\immersive-release-3.0.0.aar')

}
</pre>
           <h4>由于没有上传到Maven仓库，这里选择jar方式添加依赖：</h4>


            <pre class="prettyprint">implementation 'com.jakewharton:butterknife:<span class="version"><em>(insert latest version)</em></span>'
annotationProcessor 'com.jakewharton:butterknife-compiler:<span class="version"><em>(insert latest version)</em></span>'</pre>

            <h3 id="license">License</h3>
            <pre class="license">Copyright 2024 AWeiLoveAndroid

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.</pre>

            <a id="ribbon" href="https://gitee.com/AWeiLoveAndroid/BreadKnife" target="_blank"><img src="static/ribbon.png" alt="Fork me on Gitee"></a>
          </div>
        </div>
      </div>
    </div>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script src="static/jquery-maven-artifact.min.js"></script>
    <script src="static/prettify.js"></script>
    <script>
      prettyPrint();
      $.fn.artifactVersion('com.lzw', 'breadknife', function(version, url) {
        $('.version').text(version);
      });
    </script>
  </body>
</html>
